﻿
// VideoPlayerDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "VideoPlayer.h"
#include "VideoPlayerDlg.h"
#include "PanoDlg.h"
#include "afxdialogex.h"
#include "Test.h"
#include "DummyDetector.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//#define MAIN_DLG_PRINT

UINT ThreadShow(PVOID pParam);
UINT ThreadRecord(PVOID pParam);
UINT ThreadDetect(PVOID pParam);
UINT ThreadShowIris(PVOID pParam);
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

	// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CVideoPlayerDlg 对话框



//初始化为关门，手动
CEvent g_eventEndShow(FALSE, TRUE);
//初始化为关门，手动
CEvent g_eventEndRecord(FALSE, TRUE);
//初始化为关门，手动
CEvent g_eventEndTrack(FALSE, TRUE);
//初始化为关门，手动
CEvent g_eventEndShowIris(FALSE, TRUE);

/*******************************************************************************
* 可见光相机回调
* @yuv      待显示帧
* @frameNo  待显示帧帧号
******************************************************************************/
void yuvCb(Mat yuv, unsigned int frameNo)
{
	ImageFrame frame;
	frame.frame = yuv;
	frame.frameNo = frameNo;
	if (g_nLightWidth == 0) {
		g_nLightWidth = yuv.cols;
		g_nLightHeight = yuv.rows;
	}
	int pos = g_pLightQueueSource->push(frame);
	//对于跳帧的处理;-1表示该帧跳掉，实际上没有push到队列
	if (pos == -1) {
		return;
	}
	//给显示线程状态置位
	//g_eventEndShow.SetEvent();
	/*if (g_pMainDlg->m_bIsShowing == FALSE) { //若显示线程没有正在显示，则显示；若正在显示则跳过
	g_pMainDlg->mShowMat = yuv.clone();
	g_eventEndShow.SetEvent();
	}
	//给存储
	if (g_pMainDlg->m_bIsRecording == TRUE && g_pMainDlg->m_bIsRecordingOneFrame == FALSE) { //若是录像模式，且没有忙于录一帧
	g_pMainDlg->mRecordMat = yuv.clone();
	g_eventEndRecord.SetEvent();
	}
	//给跟踪
	bool trackReady = true;
	if (trackReady) { //
	g_pMainDlg->mTrackMat = yuv.clone();
	g_eventEndTrack.SetEvent();
	}*/
}

/*******************************************************************************
* 红外相机回调
* @yuv      待显示帧
* @frameNo  待显示帧帧号
******************************************************************************/
void yuvCb2(Mat yuv, unsigned int frameNo)
{
	ImageFrame frame;
	frame.frame = yuv;
	frame.frameNo = frameNo;
	int pos = g_pIrisQueue->push(frame);
	//对于跳帧的处理
	if (pos == -1) {
		return;
	}
	//给显示线程状态置位
	g_eventEndShowIris.SetEvent();
}

CVideoPlayerDlg::CVideoPlayerDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(IDD_VIDEOPLAYER_DIALOG, pParent)
	, m_strShowFrm(_T(""))
	, m_nFrmDelay(50)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_bIsPaused = false;
	m_bIsStarted = false;
#pragma region AutoFit
	m_ptMinTrackSize.x = 0;
	m_ptMinTrackSize.y = 0;
#pragma endregion
	m_nEnhanceMode = 0;
}

#pragma region AutoFit
CVideoPlayerDlg::~CVideoPlayerDlg()
{
	FreeCtrlInfoList();
}

void CVideoPlayerDlg::SetMinSize(int nWidth, int nHeight)
{
	ASSERT(nWidth > 0);
	ASSERT(nHeight > 0);

	//设置窗口最小值
	m_ptMinTrackSize.x = nWidth;
	m_ptMinTrackSize.y = nHeight;
}

void CVideoPlayerDlg::FreeCtrlInfoList()
{
	INT_PTR	nCount = m_listCtrlInfo.GetSize();

	for (int i = 0; i < nCount; i++)
	{
		lpControlInfo pCtrlInfo = m_listCtrlInfo.ElementAt(i);
		delete pCtrlInfo;
	}

	m_listCtrlInfo.RemoveAll();
}

void CVideoPlayerDlg::MakeCtrlFit(CWnd* pWnd, int nMoveXPercent, int nMoveYPercent, int nZoomXPercent, int nZoomYPercent)
{
	ASSERT(pWnd);									//指针是否为空
	ASSERT(nMoveXPercent >= 0 && nMoveXPercent <= 100);	//nMoveXPercent值是否有效
	ASSERT(nMoveYPercent >= 0 && nMoveYPercent <= 100);	//nMoveXPercent值是否有效
	ASSERT(nZoomXPercent >= 0 && nZoomXPercent <= 100);	//nMoveXPercent值是否有效
	ASSERT(nZoomYPercent >= 0 && nZoomYPercent <= 100);	//nMoveXPercent值是否有效

	lpControlInfo	pCtrlInfo = new ControlInfo;	//创建结构指针

													//填充变量
	pCtrlInfo->m_pWnd = pWnd;
	pCtrlInfo->m_nMoveXPercent = nMoveXPercent;
	pCtrlInfo->m_nMoveYPercent = nMoveYPercent;
	pCtrlInfo->m_nZoomXPercent = nZoomXPercent;
	pCtrlInfo->m_nZoomYPercent = nZoomYPercent;

	pWnd->GetWindowRect(pCtrlInfo->m_rectWnd);
	ScreenToClient(&pCtrlInfo->m_rectWnd);

	m_listCtrlInfo.Add(pCtrlInfo);	//加入维护列表
}

void CVideoPlayerDlg::CancelCtrlFit(HWND hWnd)
{
	INT_PTR	nCount = m_listCtrlInfo.GetSize();

	for (int i = 0; i < nCount; i++)
	{
		lpControlInfo pCtrlInfo = m_listCtrlInfo.ElementAt(i);
		if (pCtrlInfo->m_pWnd->GetSafeHwnd() == hWnd)
		{
			delete pCtrlInfo;
			m_listCtrlInfo.RemoveAt(i);

			break;
		}
	}
}

void CVideoPlayerDlg::OnSize(UINT nType, int cx, int cy)
{
	//计算窗口宽度和高度的改变量
	int nIncrementX = cx - m_nWinWidth;
	int nIncrementY = cy - m_nWinHeight;

	INT_PTR	nCount = m_listCtrlInfo.GetSize();

	UINT	uFlags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOCOPYBITS;
	for (int i = 0; i < nCount; i++)
	{
		//获取变化控制系数
		int	nMoveXPercent = m_listCtrlInfo[i]->m_nMoveXPercent;
		int	nMoveYPercent = m_listCtrlInfo[i]->m_nMoveYPercent;
		int	nZoomXPercent = m_listCtrlInfo[i]->m_nZoomXPercent;
		int	nZoomYPercent = m_listCtrlInfo[i]->m_nZoomYPercent;

		CWnd*	pWndCtrl = m_listCtrlInfo[i]->m_pWnd;
		HWND	hWnd = pWndCtrl->GetSafeHwnd();
		if ((NULL != pWndCtrl) && IsWindow(hWnd))
		{
			int nLeft = m_listCtrlInfo[i]->m_rectWnd.left;
			int nTop = m_listCtrlInfo[i]->m_rectWnd.top;
			int nWidth = m_listCtrlInfo[i]->m_rectWnd.Width();
			int nHeight = m_listCtrlInfo[i]->m_rectWnd.Height();

			//设置新的位置参数
			nLeft += (nIncrementX*nMoveXPercent / 100);
			nTop += (nIncrementY*nMoveYPercent / 100);
			nWidth += (nIncrementX*nZoomXPercent / 100);
			nHeight += (nIncrementY*nZoomYPercent / 100);

			//  把控件移动到新位置
			pWndCtrl->MoveWindow(nLeft, nTop, nWidth, nHeight);

		}

	}
	if (GetDlgItem(IDC_PIC) != NULL)
		GetDlgItem(IDC_PIC)->GetClientRect(&m_rectPic);
	if (GetDlgItem(IDC_PIC2) != NULL)
		GetDlgItem(IDC_PIC2)->GetClientRect(&m_rectPic2);
	Invalidate(TRUE);//强制刷新窗口，防止出现鬼影
	UpdateWindow(); //updateWindow必须和invalidate配合使用才能有效果
	if(m_frmCtl.m_bIsInitialized && m_frmCtl.GetFrameIdx() != -1) //防止未初始化的时候读取到错误帧
		OnDisplay(m_frmCtl.GetCurrentFrame()); //防止暂停后拖动窗口被背景色填充掉
	CDialogEx::OnSize(nType, cx, cy);

	// TODO: 在此处添加消息处理程序代码
}


void CVideoPlayerDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	//设置窗口的最小大小
	lpMMI->ptMinTrackSize = m_ptMinTrackSize;

	CDialogEx::OnGetMinMaxInfo(lpMMI);
}


#pragma endregion

void CVideoPlayerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CVideoPlayerDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BTN_START, &CVideoPlayerDlg::OnBnClickedBtnStart)
	ON_WM_SIZE()
	ON_WM_GETMINMAXINFO()
	ON_BN_CLICKED(IDC_BTN_RECORD1, &CVideoPlayerDlg::OnBnClickedBtnRecord)
	ON_BN_CLICKED(IDC_BUTTON_CAPTURE, &CVideoPlayerDlg::OnBnClickedButtonCapture)
	ON_BN_CLICKED(IDC_BUTTON_PARA, &CVideoPlayerDlg::OnBnClickedButtonPara)
	ON_BN_CLICKED(IDC_BTN_START2, &CVideoPlayerDlg::OnBnClickedBtnStart2)
	ON_BN_CLICKED(IDC_BUTTON_ENHANCE, &CVideoPlayerDlg::OnBnClickedButtonEnhance)
	ON_BN_CLICKED(IDC_BUTTON_AREA, &CVideoPlayerDlg::OnBnClickedButtonArea)
	ON_BN_CLICKED(IDC_BUTTON_LINE, &CVideoPlayerDlg::OnBnClickedButtonLine)
	ON_WM_RBUTTONDOWN()
//	ON_COMMAND(ID_32773, &CVideoPlayerDlg::On32773)
ON_COMMAND(ID_TRACK_ADD, &CVideoPlayerDlg::OnTrackAdd)
ON_COMMAND(ID_TRACK_CANCEL, &CVideoPlayerDlg::OnTrackCancel)
END_MESSAGE_MAP()


// CVideoPlayerDlg 消息处理程序

BOOL CVideoPlayerDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	GetDlgItem(IDC_PIC)->GetClientRect(&m_rectPic);
	GetDlgItem(IDC_PIC2)->GetClientRect(&m_rectPic2);
#ifdef PLAY_YUV
	this->SetWindowTextW(_T("YUV播放器 By YXP"));
#endif
#ifdef PLAY_SEQ
	this->SetWindowTextW(_T("序列图播放器 By YXP"));
#endif

#pragma region AutoFit
	CRect	rectTemp;

	//获取客户区大小
	GetClientRect(rectTemp);
	//保存客户区信息
	m_nWinWidth = rectTemp.Width();
	m_nWinHeight = rectTemp.Height();
	//获取窗口大小
	GetWindowRect(rectTemp);
	//设置窗口最小值
	SetMinSize(rectTemp.Width(), rectTemp.Height());

	//适配控件
	MakeCtrlFit(GetDlgItem(IDC_PIC), 0, 0, 100, 100);
	MakeCtrlFit(GetDlgItem(IDC_PIC2), 0, 0, 100, 100);

	MakeCtrlFit(GetDlgItem(IDC_BTN_START), 0, 100, 20); //前两个参数用于控制位置的变动(不考虑缩放)(值代表其所在行或列的起始位置百分比)

#pragma endregion

	g_pMainDlg = this;
	//创建可见光图像队列：视频源
	if (g_pLightQueue == NULL) {
		int lightSampleRate = atoi(CUtils::getCfgString("light_sample_rate").c_str());
		int lightQueueDepth = atoi(CUtils::getCfgString("light_queue_depth").c_str());
		g_pLightQueueSource = new CImageQueueManager(lightQueueDepth, lightSampleRate); 
	}
	//创建可见光图像队列：清晰化输出
	if (g_pLightQueue == NULL) {
		int lightQueueDepth2 = atoi(CUtils::getCfgString("light_queue_depth").c_str());
		g_pLightQueue = new CImageQueueManager(lightQueueDepth2, 1);
	}
	//创建红外图像队列
	if (g_pIrisQueue == NULL) {
		int irisSampleRate = atoi(CUtils::getCfgString("iris_sample_rate").c_str());
		int irisQueueDepth = atoi(CUtils::getCfgString("iris_queue_depth").c_str());
		g_pIrisQueue = new CImageQueueManager(irisQueueDepth, irisSampleRate); 
	}
	//创建检测识别结果队列
	if (g_pDetOutQueue == NULL) {
		int detQueueDepth = atoi(CUtils::getCfgString("detect_output_queue_depth").c_str());
		g_pDetOutQueue = new CDetectOutputQueueManager(detQueueDepth); 
	}
	//创建全景图像队列
	if (g_pPanoQueue == NULL) {
		int panoInterval = atoi(CUtils::getCfgString("pano_interval").c_str());
		int panoQueueDepth = atoi(CUtils::getCfgString("pano_queue_depth").c_str());
		g_pPanoQueue = new CImageQueueManager(panoQueueDepth, panoInterval);
	}
	//启动清晰化算法
	if (g_pEnhancerWrapper == NULL) {
		//在该构造函数内部创建工作线程进行清晰化
		g_pEnhancerWrapper = new CImageEnhancerWrapper(g_pLightQueueSource, g_pLightQueue, g_pPanoQueue);
	}
	//启动可见光显示线程
	pShowThread = AfxBeginThread(ThreadShow, 0, THREAD_PRIORITY_ABOVE_NORMAL, 0, CREATE_SUSPENDED);
	pShowThread->m_bAutoDelete = FALSE;
	pShowThread->ResumeThread();
	//启动红外显示线程
	pShowThreadIris = AfxBeginThread(ThreadShowIris, 0, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
	pShowThreadIris->m_bAutoDelete = FALSE;
	pShowThreadIris->ResumeThread();
	//启动检测识别算法
	if (g_pDummyDetector == NULL) {
		//在该构造函数内部创建工作线程进行检测识别；输入可见光图像队列以及检测输出队列
		g_pDummyDetector = new CDummyDetector(0, g_pLightQueue, g_pDetOutQueue);
	}
	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void CVideoPlayerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CVideoPlayerDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CVideoPlayerDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



static DWORD ThreadSendID;
void CVideoPlayerDlg::OnBnClickedBtnStart()
{

#ifdef PLAY_YUV

	CFileDialog fDlg(true); 
	if (fDlg.DoModal() == IDCANCEL)
		return;
	CString YUVFileName = fDlg.GetPathName();
	if (fDlg.GetFileExt() != _T("yuv") && fDlg.GetFileExt() != _T("YUV"))
	{
		MessageBox(_T("请打开yuv格式的文件!"));
		return;
	}
	//弹出对话框选择帧大小
	CDlgYUVParams dlg;
	if (dlg.DoModal() == IDOK)
	{
		this->m_nFrmHeight = dlg.m_nFrmHeight;
		this->m_nFrmWidth = dlg.m_nFrmWidth;
	}
	else
		return;

	m_frmCtl.InitParams(YUVFileName, m_nFrmWidth, m_nFrmHeight);

#endif // PLAY_YUV

	m_frmCtl.setCb(yuvCb);
	m_frmCtl.fetch_yuv();
	m_bIsPaused = false;
	m_bIsStarted = true;
}

inline int getFrameNo(CImageQueueManager *manager) {
	return manager->getLastFrameNo();
}

/*******************************************************************************
* 可见光显示线程
* @yuv      待显示帧
* @frameNo  待显示帧帧号
******************************************************************************/
UINT ThreadShow(PVOID pParam) {
	static unsigned int prevNo = 0;
	while (true)
	{
		int no = g_pLightQueue->getLastFrameNo();
		//队列为空（尚未开机）
		if (no == 0) {
			Sleep(500);
			continue;
		}
		//该帧显示过，不做处理
		if (no <= prevNo) {
			continue;
		}
		ImageFrame frame;
		g_pLightQueue->getLast(frame);
		//此处一定要clone，否则在onDisplay中进行的绘制操作，都会被其他模块中getLast时带入
		frame.frame = frame.frame.clone();
		g_pMainDlg->OnDisplay(frame.frame);
		prevNo = frame.frameNo;
	}
}

/*******************************************************************************
* 红外显示线程
* @yuv      待显示帧
* @frameNo  待显示帧帧号
******************************************************************************/
UINT ThreadShowIris(PVOID pParam) {
	static unsigned int prevNo = 0;
	while (true)
	{
		int no = g_pIrisQueue->getLastFrameNo();
		//队列为空（尚未开机）
		if (no == 0) {
			Sleep(500);
			continue;
		}
		//该帧显示过，不做处理
		if (g_pIrisQueue->getLastFrameNo() <= prevNo) {
			continue;
		}
		ImageFrame frame;
		g_pIrisQueue->getLast(frame);
		g_pMainDlg->OnDisplay2(frame.frame);
		prevNo = frame.frameNo;
	}
}


//录像线程
UINT ThreadRecord(PVOID pParam) {
	while (true)
	{
		::WaitForSingleObject(g_eventEndRecord, INFINITE);
		if (g_pMainDlg->m_bIsRecording == false) {
			//g_pMainDlg->writer.release();
			break;
		}
		g_pMainDlg->m_bIsRecordingOneFrame = true;
		g_pMainDlg->writer.write(g_pMainDlg->mRecordMat);
		g_pMainDlg->m_bIsRecordingOneFrame = false;
		g_eventEndRecord.ResetEvent();
	}
	return 0;
}

//跟踪：模拟用途ONLY
void simTrack(Mat mat, int *x, int *y, int *w, int *h) {
	static int i = 0;
	*x = i;
	*y = i + 20;
	*w = i * 10 % 20 + i * 10 % 20;
	*h = i * 10 % 20 + i * 10 % 20;
	*x = *x % 600;
	*y = *y % 600;
	*w = *w % 600;
	*h = *h % 600;
	i += 10;
}
//跟踪线程
UINT ThreadDetect(PVOID pParam) {
	while (true)
	{
		::WaitForSingleObject(g_eventEndTrack, INFINITE);
		simTrack(g_pMainDlg->mTrackMat, &g_pMainDlg->x, &g_pMainDlg->y, &g_pMainDlg->w, &g_pMainDlg->h);
		Sleep(100);
		g_eventEndTrack.ResetEvent();
	}
	return 0;
}

/*******************************************************************************
* 负责显示到可见光界面
* @curFrame 待显示帧     
* @return   void
******************************************************************************/
void CVideoPlayerDlg::OnDisplay(cv::Mat curFrame)  
{
	int static firstTime = 1;
#ifdef MAIN_DLG_PRINT
	SYSTEMTIME st1, st1_1, st1_2, st1_3, st1_4, st1_5, st2;
	GetLocalTime(&st1);
	cout << "display st1 = " << st1.wHour << " " << st1.wMinute << " " << st1.wSecond << " " << st1.wMilliseconds << endl;
#endif // MAIN_DLG_PRINT	
	DetectOutput out;
	//从检测识别结果队列中获取最新的结果，若不为空（ok != -1）则进行画框处理
	int ok = g_pDummyDetector->m_outQ->getLast(out);
	if (ok != -1) { 
		int len = out.result.size();
		for (int i = 0; i < len; i++) {
			Rect r = out.result[i].first;
			string s = out.result[i].second;
			//OpenCV默认序是BGR
			cv::rectangle(curFrame, cvPoint(r.x, r.y), cvPoint(r.x+r.width, r.y+r.height), Scalar(0, 0, 255), 2, 1, 0);
		}
	}
	//画区域检测的框
	int areaNum = m_areas.size();
	for (int i = 0; i < areaNum; i++) {
		Box b = m_areas[i];
		cv::rectangle(curFrame, cvPoint(b.x, b.y), cvPoint(b.x + b.w, b.y + b.h), Scalar(0, 0, 255), 2, 1, 0);
	}
	//画越界检测的线
	int lineNum = m_lineV.size();
	for (int i = 0; i < lineNum; i++) {
		vector<CvPoint> line = m_lineV[i];
		for (int j = 0; j < (line.size() - 1); j++) {
			CvPoint p1 = cvPoint(line[j].x, line[j].y);
			CvPoint p2 = cvPoint(line[j + 1].x, line[j + 1].y);
			cv::line(curFrame, p1, p2, Scalar(0, 0, 255), 2, 1, 0);
		}
	}
#ifdef MAIN_DLG_PRINT
	GetLocalTime(&st1_2);
	cout << "display st1_2 = " << st1_2.wHour << " " << st1_2.wMinute << " " << st1_2.wSecond << " " << st1_2.wMilliseconds << endl;
#endif // MAIN_DLG_PRINT
	IplImage iplImage(curFrame); //转换成IplImage类型，用于显示
#ifdef MAIN_DLG_PRINT
	GetLocalTime(&st1_3);
	cout << "display st1_3 = " << st1_3.wHour << " " << st1_3.wMinute << " " << st1_3.wSecond << " " << st1_3.wMilliseconds << endl;
#endif // MAIN_DLG_PRINT

	CDC* pDC = GetDlgItem(IDC_PIC)->GetDC();
	CvvImage cvImg;
	cvImg.CopyOf(&iplImage);
#ifdef MAIN_DLG_PRINT
	GetLocalTime(&st1_4);
	cout << "display st1_4 = " << st1_4.wHour << " " << st1_4.wMinute << " " << st1_4.wSecond << " " << st1_4.wMilliseconds << endl;
#endif // MAIN_DLG_PRINT
	cvImg.DrawToHDC(pDC->m_hDC, &m_rectPic);
#ifdef MAIN_DLG_PRINT
	GetLocalTime(&st1_5);
	cout << "display st1_5 = " << st1_5.wHour << " " << st1_5.wMinute << " " << st1_5.wSecond << " " << st1_5.wMilliseconds << endl;
#endif // MAIN_DLG_PRINT
	
	ReleaseDC(pDC);
#ifdef MAIN_DLG_PRINT
	GetLocalTime(&st2);
	cout << "display st2 = " << st2.wHour << " " << st2.wMinute << " " << st2.wSecond << " " << st2.wMilliseconds << endl;
#endif // MAIN_DLG_PRINT
}

/*******************************************************************************
* 负责显示到红外界面
* @curFrame 待显示帧
* @return   void
******************************************************************************/
void CVideoPlayerDlg::OnDisplay2(cv::Mat curFrame)
{
	CvSize newsize;
	newsize.width = m_rectPic.Width();
	newsize.height = m_rectPic.Height();
	Mat imgResized;
	imgResized.create(newsize, CV_8UC3);
	resize(curFrame, imgResized, imgResized.size());
	DetectOutput out;
	int ok = g_pDummyDetector->m_outQ->getLast(out);
	if (ok != -1) {
		int len = out.result.size();
		for (int i = 0; i < len; i++) {
			Rect r = out.result[i].first;
			string s = out.result[i].second;
			cv::rectangle(imgResized, cvPoint(r.x, r.y), cvPoint(r.x + r.width, r.y + r.height), Scalar(0, 0, 255), 2, 1, 0);
		}
	}
	IplImage iplImage(imgResized); //转换成IplImage类型
	cout << "on display" << endl;
	CDC* pDC = GetDlgItem(IDC_PIC2)->GetDC();
	CvvImage cvImg;
	cvImg.CopyOf(&iplImage);
	cvImg.DrawToHDC(pDC->m_hDC, &m_rectPic);
}

void CVideoPlayerDlg::OnBnClickedBtnRecord()
{
	// TODO: 在此添加控件通知处理程序代码
	//打开录像句柄
	int codec = CV_FOURCC('M', 'J', 'P', 'G');// VideoWriter::fourcc('M', 'J', 'P', 'G');
	double fps = 15.0;
	bool isColor = true;
	string filename = "live.avi";
	Size sizeFrame(m_nFrmWidth, m_nFrmHeight);
	writer.open(filename, codec, fps, sizeFrame, isColor);
	if (!writer.isOpened())
	{
		cout << "Could not open the output video for write: " << endl;
		return ;
	}
	m_bIsRecording = !m_bIsRecording;
	if (m_bIsRecording == true) {
		//启动录像线程
		pShowThread = AfxBeginThread(ThreadRecord, 0, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
		pShowThread->m_bAutoDelete = TRUE;
		pShowThread->ResumeThread();
	}
	SetDlgItemText(IDC_BTN_RECORD1, m_bIsRecording == true ? _T("停止") : _T("录像"));
}


void CVideoPlayerDlg::OnBnClickedButtonCapture()
{
	// TODO: 在此添加控件通知处理程序代码
	ImageFrame frame;
	int r = g_pIrisQueue->getLast(frame);
	if (r == -1) return;
	imwrite("./capture.jpg", frame.frame);
}

/**
* 点击全景
*/
void CVideoPlayerDlg::OnBnClickedButtonPara()
{
	// TODO: 在此添加控件通知处理程序代码
	pTD = new CPanoDlg();
	pTD->Create(IDD_DIALOG_PARA); //创建一个非模态对话框
	pTD->ShowWindow(SW_SHOWNORMAL);
}

/**
* 进入全景模式
*/
void CVideoPlayerDlg::OnBnClickedBtnStart2()
{
	// TODO: 在此添加控件通知处理程序代码
	//启动红外线程数据
	string url = CUtils::getCfgString("sim_rtsp_url");
	m_frmCtl2 = new CRtspSource(url);
	m_frmCtl2->setCb(yuvCb2);
	m_frmCtl2->fetch_yuv2();
}

/**
* 切换清晰化开关
*/
void CVideoPlayerDlg::OnBnClickedButtonEnhance()
{
	// TODO: 在此添加控件通知处理程序代码
	m_nEnhanceMode = m_nEnhanceMode == 0 ? 1 : 0;
	CString caption = m_nEnhanceMode == 1 ? _T("关闭清晰化") : _T("开启清晰化");
	g_pEnhancerWrapper->setMode(m_nEnhanceMode);
	SetDlgItemTextW(IDC_BUTTON_ENHANCE, caption);
}


void CVideoPlayerDlg::OnBnClickedButtonArea()
{
	// TODO: 在此添加控件通知处理程序代码
	CAreaDlg dlg; 
	dlg.DoModal();
	//cout << m_areaX << m_areaY << m_areaW << m_areaH << endl;
}


void CVideoPlayerDlg::OnBnClickedButtonLine()
{
	// TODO: 在此添加控件通知处理程序代码
	CLineDlg dlg;
	dlg.DoModal();
	//cout << m_lineV.size() << m_lineV[0].x << endl;
	
}

void CVideoPlayerDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	int index = -1;
	CPoint rcPoint = point;
	CRect rect;
	GetDlgItem(IDC_PIC)->GetWindowRect(&rect);
	CUtils::getRelativePos(this, m_rectPic, rect, g_nLightWidth, g_nLightHeight, rcPoint);
	m_TrackPoint = rcPoint;
	CMenu menu;
	menu.LoadMenu(IDR_MENU2); //装载自定义的右键菜单 
	CMenu *pContextMenu = menu.GetSubMenu(0); //获取第一个弹出菜单，所以第一个菜单必须有子菜单 
	CPoint point1;//定义一个用于确定光标位置的位置  
	GetCursorPos(&point1);//获取当前光标的位置，以便使得菜单可以跟随光标  
	pContextMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point1.x, point1.y, this); //在指定位置显示弹出菜单
	CDialogEx::OnRButtonDown(nFlags, point);
}


void CVideoPlayerDlg::OnTrackAdd()
{
	// TODO: 在此添加命令处理程序代码
	g_pDummyDetector->SetTrackPoint(cvPoint(m_TrackPoint.x, m_TrackPoint.y));
}


void CVideoPlayerDlg::OnTrackCancel()
{
	// TODO: 在此添加命令处理程序代码
	g_pDummyDetector->EndTrack();
}
